package com.wk.wms.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.wk.common.constant.RedisKey;
import com.wk.common.constant.mq.ItemExchange;
import com.wk.common.constant.mq.ItemRoutingKey;
import com.wk.wms.entity.WareSku;
import com.wk.wms.mapper.WareSkuMapper;
import com.wk.wms.service.WareSkuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wk.wms.vo.SkuLockVO;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class WareSkuServiceImpl extends ServiceImpl<WareSkuMapper, WareSku> implements WareSkuService {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 检查并锁定下单商品的库存
     */
    @Transactional
    @Override
    public String checkAndLockStore(List<SkuLockVO> skuLockVOs) {

        if (CollectionUtils.isEmpty(skuLockVOs)) {
            return "请选中商品";
        }

        //校验并锁定库存
        skuLockVOs.forEach(this::lockStock);

        //过滤出锁定失败的商品
        List<SkuLockVO> unLockSkus = skuLockVOs.stream().filter(skuLockVO -> !skuLockVO.getLocked()).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(unLockSkus)) {
            //解锁之前锁定成功的商品库存
            skuLockVOs
                .stream()
                .filter(SkuLockVO::getLocked)
                .collect(Collectors.toList())
                .forEach(skuLockVO -> baseMapper.unLockStock(skuLockVO));

            //提示锁定失败的商品
            List<Long> skuIds = unLockSkus.stream().map(SkuLockVO::getSkuId).collect(Collectors.toList());
            return "下单失败,商品:"+skuIds+"库存不足";
        }

        //将库存锁定成功的商品信息放入Redis 用于订单创建失败解锁对应库存
        String orderToken = skuLockVOs.get(0).getOrderToken();
        redisTemplate.boundValueOps(RedisKey.STOCK_LOCK + orderToken).set(JSON.toJSONString(skuLockVOs));


        //将库存锁定成功的商品信息发送到延时消息队列 用于解锁商品库存锁定成功但出现异常未能成功创建订单的商品库存
        amqpTemplate.convertAndSend(ItemExchange.ORDER_EXCHANGE, ItemRoutingKey.STOCK_TTL,orderToken);

        return null;
    }

    /**
     * 查询商品剩余库存是否足够
     * 如果足够则锁定库存(需要分布式锁)
     */
    private void lockStock(SkuLockVO skuLockVO) {

        //添加分布式锁 锁定当前商品 避免超卖
        RLock lock = redissonClient.getLock("stockLock" + skuLockVO.getSkuId());
        lock.lock();

        //查询商品库存足够的仓库
        List<WareSku> wareSkus =baseMapper.checkStock(skuLockVO);

        if (CollectionUtils.isNotEmpty(wareSkus)) {
            //锁定第一个库存足够的仓库
            skuLockVO.setWareSkuId(wareSkus.get(0).getId());
            baseMapper.lockStock(skuLockVO);

            //标记锁定成功 以便后续处理
            skuLockVO.setLocked(true);
        }else{
            //库存不足 锁定失败
            skuLockVO.setLocked(false);
        }


        //释放分布式锁
        lock.unlock();
    }
}
